// CTrayIconDemoDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CSMTServerApp.h"
#include "CSMTServerDlg.h"
#include "MouseMsgHandlerImpl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSMTServerDlg dialog

CSMTServerDlg::CSMTServerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSMTServerDlg::IDD, pParent)
	, m_rbNetworkProtocol(1)
	, m_rbOSCFormat(FALSE)
	, m_chkSysMouse(FALSE)
	, m_chkFlipV(FALSE)
	, m_chkFlipH(FALSE)
	, m_chkRelative(FALSE)
	, m_iWidth(0)
	, m_iHeight(0)
	, m_iPort(0)
	, m_pCMTServer(NULL)
	, m_pTrayIcon(NULL)
{
	//{{AFX_DATA_INIT(CSMTServerDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
}

void CSMTServerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSMTServerDlg)
	// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP

	DDX_Control(pDX, IDC_IPADDRESS1, m_ip);
	DDX_Control(pDX, IDC_COMBO_SENSOR, m_devID);
	DDX_Control(pDX, IDC_BUTTON_UPDATE, m_bntUpdate);
	DDX_Control(pDX, IDC_BUTTON_STOP, m_bntStop);
	DDX_Control(pDX, IDC_BUTTON_START, m_bntStart);
	DDX_Control(pDX, IDC_STATIC_STATE, m_state);
	DDX_Radio(pDX, IDC_RB_UDP, m_rbNetworkProtocol);
	DDX_Radio(pDX, IDC_RB_OSC_RAW, m_rbOSCFormat);
	DDX_Check(pDX, IDC_CHECK_SYS_MOUSE, m_chkSysMouse);
	DDX_Check(pDX, IDC_CHECK_FLIPV, m_chkFlipV);
	DDX_Check(pDX, IDC_CHECK_FLIPH, m_chkFlipH);
	DDX_Check(pDX, IDC_CHECK_RELATIVE, m_chkRelative);
	DDX_Text(pDX, IDC_EDIT_WIDTH, m_iWidth);
	DDX_Text(pDX, IDC_EDIT_HEIGHT, m_iHeight);
	DDX_Text(pDX, IDC_EDIT_PORT, m_iPort);
}

BEGIN_MESSAGE_MAP(CSMTServerDlg, CDialog)
	//{{AFX_MSG_MAP(CSMTServerDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_COMMAND(IDR_TASKBAR_MENU_ABOUT, OnAbout)
	ON_COMMAND(IDR_TASKBAR_MENU_SHOW, OnShow)
	ON_COMMAND(IDR_TASKBAR_MENU_EXIT, OnCancel)
	//}}AFX_MSG_MAP
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_RB_OSC_XML, &CSMTServerDlg::OnBnClickedRbOscXml)
	ON_BN_CLICKED(IDC_RB_UDP, &CSMTServerDlg::OnBnClickedRbUdp)
	ON_BN_CLICKED(IDC_RB_TCP, &CSMTServerDlg::OnBnClickedRbTcp)
	ON_NOTIFY(IPN_FIELDCHANGED, IDC_IPADDRESS1, &CSMTServerDlg::OnIpnFieldchangedIpaddress1)
	ON_EN_CHANGE(IDC_EDIT_PORT, &CSMTServerDlg::OnEnChangeEditPort)
	ON_BN_CLICKED(IDC_RB_OSC_RAW, &CSMTServerDlg::OnBnClickedRbOscRaw)
	ON_CBN_SELCHANGE(IDC_COMBO_SENSOR, &CSMTServerDlg::OnCbnSelchangeComboSensor)
	ON_EN_CHANGE(IDC_EDIT_WIDTH, &CSMTServerDlg::OnEnChangeEditWidth)
	ON_EN_CHANGE(IDC_EDIT_HEIGHT, &CSMTServerDlg::OnEnChangeEditHeight)
	ON_BN_CLICKED(IDC_CHECK_SYS_MOUSE, &CSMTServerDlg::OnBnClickedCheckSysMouse)
	ON_BN_CLICKED(IDC_CHECK_FLIPV, &CSMTServerDlg::OnBnClickedCheckFlipv)
	ON_BN_CLICKED(IDC_CHECK_FLIPH, &CSMTServerDlg::OnBnClickedCheckFliph)
	ON_BN_CLICKED(IDC_CHECK_RELATIVE, &CSMTServerDlg::OnBnClickedCheckRelative)
	ON_BN_CLICKED(IDC_BUTTON_UPDATE, &CSMTServerDlg::OnBnClickedButtonUpdate)
	ON_BN_CLICKED(IDC_BUTTON_STOP, &CSMTServerDlg::OnBnClickedButtonStop)
	ON_BN_CLICKED(IDC_BUTTON_START, &CSMTServerDlg::OnBnClickedButtonStart)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSMTServerDlg message handlers

BOOL CSMTServerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// Load settings from ini file
	//
	CWinApp* pApp = AfxGetApp();
	m_chkFlipV = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("FlipV"), 0);
	m_chkFlipH = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("FlipH"), 0);
	m_chkRelative = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("Relative"), 1);
	m_chkSysMouse =pApp->GetProfileInt(_T("SMT_DEVICE"), _T("SysMouse"), 0);
	m_rbNetworkProtocol = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("NetworkProtocol"), 1);
	m_rbOSCFormat = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("OSCFormat"), 1);
	m_iWidth = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("DevWidth"), 1280);
	m_iHeight = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("DevHeight"), 960);
	m_iPort = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("Port"), 3000);
	m_devID.SetCurSel(pApp->GetProfileInt(_T("SMT_DEVICE"), _T("Sensor"), 0));
	DWORD ip = pApp->GetProfileInt(_T("SMT_DEVICE"), _T("IP"), 2130706433); // 127.0.0.1
	m_ip.SetAddress(ip);	

	UpdateData(FALSE);

	// Create the SMT server
	//
	m_cmtProps.iSize = sizeof(CMTCMTDriveServerProps);
	m_cmtProps.bFlipH = m_chkFlipH;
	m_cmtProps.bFlipV = m_chkFlipV;
	m_cmtProps.bRelative = m_chkRelative;
	m_cmtProps.bSysMouse = m_chkSysMouse;
	m_cmtProps.bUDP = m_rbNetworkProtocol == 1 ? false : true;
	m_cmtProps.dwIP = ip;
	m_cmtProps.lPort = m_iPort;
	m_cmtProps.lHeight = m_iHeight;
	m_cmtProps.lWidth = m_iWidth;
	m_cmtProps.oscFormat = static_cast<OSCFormat>(m_rbOSCFormat);
	m_pCMTServer = new CMTDriveServer();
	m_pCMTServer->InitServer(m_cmtProps, GetSafeHwnd(), m_state.GetDlgCtrlID());
	
	// Declare an array of MouseMsgHandlerPtr of size 3, to handle three types of mouse events
	MouseMsgHandlerPtr *pHandler = new MouseMsgHandlerPtr [3];
	
	// Define an object of CRightMouseClickMsgHandler for handling right mouse button click events
	MouseMsgHandlerPtr rbcHandler = new CRightMouseClickMsgHandler();

	// Define an object of CLeftMouseDblClickMsgHandler for handling left mouse button double click events
	MouseMsgHandlerPtr lbcHandler = new CLeftMouseDblClickMsgHandler();

	// Define an object of CMouseHoverMsgHandler for handling mouse hover events
	MouseMsgHandlerPtr mhHandler = new CMouseHoverMsgHandler(m_pTrayIcon);

	pHandler[0] = lbcHandler;
	pHandler[1] = rbcHandler;
	pHandler[2] = mhHandler;

	// Declare an array of IconDataPtr of size 2, to add two sets of icons. 
	// Only one will be active though.
	CIconData *pIconData = new CIconData(IDI_ICON1, _T("Stantum MultiTouch Driver"));

	// Define the CTrayIcon object
	m_pTrayIcon = new CTrayIcon(pHandler, 3, pIconData);

	// Refer the CTrayIcon object to the CMouseHoverMsgHandler object, for handling mouse events
	((CMouseHoverMsgHandler*)mhHandler)->SetTrayIcon(m_pTrayIcon);
	m_pTrayIcon->ShowIcon();
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

bool CSMTServerDlg::SetCMTServerProps(const CMTCMTDriveServerProps &props)
{
	if(!m_pCMTServer)
		return false;

	return m_pCMTServer->UpdateServer(props);
}

void CSMTServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSMTServerDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSMTServerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CSMTServerDlg::OnAbout() 
{
	CAboutDlg aDlg;
	aDlg.DoModal();
}

void CSMTServerDlg::OnShow() 
{
	if(IsIconic())
	{
		//m_pTrayIcon->HideIcon();
		ShowWindow(SW_SHOWNORMAL);		
	}
	else
		ShowWindow(SW_SHOW);
}

void CSMTServerDlg::OnCancel() 
{	
	CDialog::OnCancel();
}

void CSMTServerDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize(nType, cx, cy);

	if(nType == SIZE_MINIMIZED)
	{
		//m_pTrayIcon->ShowIcon();
		ShowWindow(SW_HIDE);
	}
}

void CSMTServerDlg::OnDestroy()
{
	CDialog::OnDestroy();

	// Safe settings to ini file
	//
	UpdateData();
	CWinApp* pApp = AfxGetApp();
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("FlipV"), m_chkFlipV);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("FlipH"), m_chkFlipH);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("Relative"), m_chkRelative);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("SysMouse"), m_chkSysMouse);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("NetworkProtocol"), m_rbNetworkProtocol);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("OSCFormat"), m_rbOSCFormat);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("DevWidth"), m_iWidth);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("DevHeight"), m_iHeight);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("Port"), m_iPort);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("Sensor"), m_devID.GetCurSel());
	DWORD ip=0;
	m_ip.GetAddress(ip);
	pApp->WriteProfileInt(_T("SMT_DEVICE"),_T("IP"), ip);

	// Shutdown the server
	//
	if(m_pCMTServer)
	{
		m_pCMTServer->ShutDown();
		delete m_pCMTServer;
		m_pCMTServer = NULL;
	}

	if(m_pTrayIcon)
	{
		delete m_pTrayIcon;
		m_pTrayIcon = NULL;
	}
}

void CSMTServerDlg::OnBnClickedRbOscXml()
{
	// Switch the network protocol to TCP!
	//
	UpdateData();
	if(m_rbNetworkProtocol == 0)
	{
		m_rbNetworkProtocol = 1;		
		m_cmtProps.oscFormat = static_cast<OSCFormat>(m_rbOSCFormat);
		m_cmtProps.bUDP = static_cast<OSCFormat>(m_rbNetworkProtocol == 1 ? false : true);
		UpdateData(FALSE);
	}	
}

void CSMTServerDlg::OnBnClickedRbOscRaw()
{
	UpdateData();
	m_cmtProps.oscFormat = static_cast<OSCFormat>(m_rbOSCFormat);
}

void CSMTServerDlg::OnBnClickedRbUdp()
{
	// Switch to OSC raw stream!
	//
	UpdateData();
	if(m_rbOSCFormat == 1)
	{
		m_rbOSCFormat = 0;		
		m_cmtProps.bUDP = static_cast<OSCFormat>(m_rbNetworkProtocol == 1 ? false : true);
		m_cmtProps.oscFormat = static_cast<OSCFormat>(m_rbOSCFormat);
		UpdateData(FALSE);
	}	
}

void CSMTServerDlg::OnBnClickedRbTcp()
{
	UpdateData();
	m_cmtProps.bUDP = static_cast<OSCFormat>(m_rbNetworkProtocol == 1 ? false : true);
}

void CSMTServerDlg::OnIpnFieldchangedIpaddress1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMIPADDRESS pIPAddr = reinterpret_cast<LPNMIPADDRESS>(pNMHDR);
	// TODO: Add your control notification handler code here
	*pResult = 0;
}

void CSMTServerDlg::OnEnChangeEditPort()
{
	UpdateData();
	m_cmtProps.lPort = m_iPort;
}

void CSMTServerDlg::OnCbnSelchangeComboSensor()
{
	/*
	UpdateData();
	m_cmtProps = m_devID.GetCurSel();
	SetCMTServerProps(m_cmtProps);
	*/
}

void CSMTServerDlg::OnEnChangeEditWidth()
{
	UpdateData();
	m_cmtProps.lWidth = m_iWidth;
}

void CSMTServerDlg::OnEnChangeEditHeight()
{
	UpdateData();
	m_cmtProps.lHeight = m_iHeight;
}

void CSMTServerDlg::OnBnClickedCheckSysMouse()
{
	UpdateData();
	m_cmtProps.bSysMouse = m_chkSysMouse;
}

void CSMTServerDlg::OnBnClickedCheckFlipv()
{
	UpdateData();
	m_cmtProps.bFlipV = m_chkFlipV;
}

void CSMTServerDlg::OnBnClickedCheckFliph()
{
	UpdateData();
	m_cmtProps.bFlipH = m_chkFlipH;
}

void CSMTServerDlg::OnBnClickedCheckRelative()
{
	UpdateData();
	m_cmtProps.bRelative = m_chkRelative;
}

void CSMTServerDlg::OnBnClickedButtonUpdate()
{
	UpdateData();
	SetCMTServerProps(m_cmtProps);	
}

void CSMTServerDlg::OnBnClickedButtonStop()
{
	if(m_pCMTServer)
		m_pCMTServer->StopServer();
}

void CSMTServerDlg::OnBnClickedButtonStart()
{
	if(m_pCMTServer)
		m_pCMTServer->StartServer();
}
